package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.heima.apis.article.IArticleClient;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.pojos.WmChannel;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.utils.common.Tess4j;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsAutoScanService;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.TesseractException;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;

@Service
@Slf4j
@Transactional
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Autowired
    private WmNewsMapper wmNewsMapper;

    /**
     * 自媒体文章审核
     *
     * @param id
     */
    @Override
    @Async //异步调用
    public void autoScanNews(Integer id) throws IOException, TesseractException, TemplateException {
        //查询文章
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews == null) {
            throw new RuntimeException("WmNewsAutoScanServiceImpl-文章不存在");
        }
        //从内容中提取纯文本内容和图片
        Map<String, Object> textAndImages = getTextAndImages(wmNews);
        System.out.println(textAndImages);
        //图片文字审核
        Boolean images = handleImageScan((List) textAndImages.get("images"), wmNews);
        if (!images) {
            return;
        }
        Boolean title = handleSensitiveScan(wmNews.getTitle(), wmNews);
        if (!title) {
            return;
        }
        //自定义敏感词过滤
        Boolean content = handleSensitiveScan(textAndImages.get("content").toString(), wmNews);
        //出现了敏感词就结束方法
        if (!content) {
            return;
        }
        //审核成功以后
        ResponseResult responseResult = saveAppArticle(wmNews);
        if (!responseResult.getCode().equals(200)) {
            throw new RuntimeException("WmNewsAutoScanServiceImpl-保存文章失败");
        }
        System.out.println(responseResult.getData());
        //回填article_id
        wmNews.setArticleId((Long) responseResult.getData());
        //修改
        wmNewsMapper.updateById(wmNews);
    }

    //下载图片
    @Autowired
    private FileStorageService fileStorageService;

    /**
     * 图片文字审核
     *
     * @param images
     * @param wmNews
     */
    private Boolean handleImageScan(List images, WmNews wmNews) throws IOException, TesseractException {
        Boolean flag = true;

        for (Object image : images) {
            byte[] bytes = fileStorageService.downLoadFile((String) image);
            ByteArrayInputStream in = new ByteArrayInputStream(bytes);
            BufferedImage imageFile = ImageIO.read(in);
            String tess4j = Tess4j.tess4j(imageFile);
            Boolean aBoolean = handleSensitiveScan(tess4j, wmNews);
            if (!aBoolean) {
                flag = aBoolean;
                return flag;
            }
        }
        return flag;
    }

    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;

    /**
     * 敏感词过滤
     *
     * @param content
     * @param wmNews
     */
    private Boolean handleSensitiveScan(String content, WmNews wmNews) {
        boolean flag = true;
        //获取所有的敏感词
        LambdaQueryWrapper<WmSensitive> queryWrapper = new LambdaQueryWrapper<>();
        List<WmSensitive> sensitiveList = wmSensitiveMapper.selectList(queryWrapper);
        List<String> wordList = new ArrayList<>();
        for (WmSensitive wmSensitive : sensitiveList) {
            wordList.add(wmSensitive.getSensitives());
        }
        //初始化工具类中的敏感词库
        SensitiveWordUtil.initMap(wordList);
        //判断是否含有敏感词
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if (map.size() > 0) {
            updateWmNews(wmNews, (short) 2, "当前文章中存在违规内容" + map);
            flag = false;
        }
        return flag;
    }

    @Autowired
    private IArticleClient iArticleClient;

    @Autowired
    private WmChannelMapper wmChannelMapper;

    @Autowired
    private WmUserMapper wmUserMapper;

    /**
     * 保存app端相关的文章数据
     *
     * @param wmNews
     */
    private ResponseResult saveAppArticle(WmNews wmNews) throws TemplateException, IOException {
        ArticleDto articleDto = new ArticleDto();
        //拷贝属性
        BeanUtils.copyProperties(wmNews, articleDto);
        //频道
        WmChannel wmChannel = wmChannelMapper.selectById(wmNews.getChannelId());
        if (wmChannel != null) {
            articleDto.setChannelName(wmChannel.getName());
        }
        //作者
        articleDto.setAuthorId(Long.valueOf(wmNews.getUserId()));
        //查询用户名称
        WmUser wmUser = wmUserMapper.selectById(wmNews.getUserId());
        if (wmUser != null) {
            articleDto.setAuthorName(wmUser.getName());
        }
        //设置文章ID（修改）
        if (wmNews.getArticleId() != null) {
            articleDto.setId(wmNews.getArticleId());
        }
        articleDto.setCreatedTime(new Date());
        //articleDto.setPublishTime(wmNews.getPublishTime());
        //调用微服务保存文章
        ResponseResult responseResult = iArticleClient.saveArticle(articleDto);
        updateWmNews(wmNews, (short) 9, "审核成功");
        return responseResult;
    }

    /**
     * 修改文章内容
     *
     * @param wmNews
     * @param status
     * @param reason
     */
    private void updateWmNews(WmNews wmNews, short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wmNewsMapper.updateById(wmNews);
    }

    /**
     * 从自媒体文章的内容中提取文本和图片
     * 提取文章的封面图片
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> getTextAndImages(WmNews wmNews) {
        StringBuilder stringBuilder = new StringBuilder();
        List<String> imagesList = new ArrayList<>();
        if (StringUtils.isNotBlank(wmNews.getContent())) {
            //先转化为集合
            List<Map> mapList = JSONArray.parseArray(wmNews.getContent(), Map.class);
            for (Map map : mapList) {
                //文本
                if (map.get("type").equals("text")) {
                    stringBuilder.append(map.get("value"));
                } else if (map.get("type").equals("image")) {
                    imagesList.add((String) map.get("value"));
                }
            }
        }
        //提取文章的封面图片
        if (StringUtils.isNotBlank(wmNews.getImages())) {
            String[] split = wmNews.getImages().split(",");
            imagesList.addAll(Arrays.asList(split));
        }

        Map<String, Object> resMap = new HashMap<>();
        resMap.put("content", stringBuilder.toString());
        resMap.put("images", imagesList);
        return resMap;
    }
}
